﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ImageProcessing.Utilities;
using ImageProcessing.DataEntryDialogs;
using ImageProcessing.IntermediateClasses;

namespace ImageProcessing
{
    public partial class MainForm : Form
    {
        private PictureControl control = new PictureControl();
        private ImageGeometry geometry = new ImageGeometry();
        int count;
        private enum arithmeticOp
        {
            add,
            sub,
            and,
            or
        };

        private int[] redArray;
        private int[] blueArray;
        private int[] greenArray;
        private int[] greyArray;

        public MainForm()
        {
            InitializeComponent();
            this.WindowState = FormWindowState.Maximized;
            this.chartHist.ChartAreas[0].AxisX.IntervalOffset = 255;
            this.count = 0;
        }

        public void DrawHistogram(int color)
        {
            try
            {
                Histogram histogram = new Histogram(this.picBoxDisplay.Image);
                if (color == 0)
                {
                    redArray = histogram.GetRedArray();
                    for (int i = 0; i < 256; i++)
                    {
                        chartHist.Series[0].Points.AddXY(i, redArray[i]);
                    }
                }
                else
                    if (color == 1)
                    {
                        greenArray = histogram.GetGreenArray();
                        for (int i = 0; i < 256; i++)
                        {
                            chartHist.Series[1].Points.AddXY(i, greenArray[i]);
                        }
                    }
                    else
                        if (color == 2)
                        {
                            blueArray = histogram.GetBlueArray();
                            for (int i = 0; i < 256; i++)
                            {
                                chartHist.Series[2].Points.AddXY(i, blueArray[i]);
                            }
                        }
                        else
                        {
                            greyArray = histogram.GetGreyArray();
                            chartHist.Series[3].Points.Clear();
                            for (int i = 0; i < 256; i++)
                            {
                                chartHist.Series[3].Points.AddXY(i, greyArray[i]);
                            }
                        }
            }
            catch
            {
                MessageBox.Show("Histogram Malfunction.");
            }
        }

        private void andToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                ArithmeticOperations arithmetic = new ArithmeticOperations((int)arithmeticOp.and);
                arithmetic.ShowDialog();
            }
            catch
            {
                MessageBox.Show("Error executing 'And' Logic operation.");
            }
        }

        private void orToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                ArithmeticOperations arithmetic = new ArithmeticOperations((int)arithmeticOp.or);
                arithmetic.ShowDialog();
            }
            catch
            {
                MessageBox.Show("Error executing 'Or' Logic operation.");
            }
        }

        private void gammaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                Dimentions dimentions = new Dimentions();
                GammaDialog dialog = new GammaDialog(ref dimentions);
                dialog.ShowDialog();
                ImageEnhancement gamma = new ImageEnhancement(this.picBoxDisplay.Image);
                this.picBoxDisplay.Image = gamma.Gamma(dimentions.DoubleValue);
                this.DrawHistogram(this.ckboxGrey.TabIndex);
            }
            catch
            {
                MessageBox.Show("Image gamma correction operation error.");
            }
        }

        private void notToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                ArithmaticLogicOperations ALOp = new ArithmaticLogicOperations();
                this.picBoxDisplay.Image = ALOp.ConvertToImageNegative(this.picBoxDisplay.Image);
                this.DrawHistogram(this.ckboxGrey.TabIndex);
            }
            catch
            {
                MessageBox.Show("Error executing 'Not' Logic operation.");
            }
        }

        private void greyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                ArithmaticLogicOperations ALOp = new ArithmaticLogicOperations();
                this.picBoxDisplay.Image = ALOp.ConvertToGreyScale(this.picBoxDisplay.Image);
                this.DrawHistogram(this.ckboxGrey.TabIndex);
            }
            catch
            {
                MessageBox.Show("Error converting image to Grey Scale.");
            }
        }

        private void brightnessToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                Dimentions dimentions = new Dimentions();
                BrightnessDialog dialog = new BrightnessDialog(ref dimentions);
                dialog.ShowDialog();
                ImageEnhancement brightness = new ImageEnhancement(this.picBoxDisplay.Image);
                this.picBoxDisplay.Image = brightness.AdjustBrightness(dimentions.Value);
                this.DrawHistogram(this.ckboxGrey.TabIndex);
            }
            catch
            {
                MessageBox.Show("Error adjusting image brightness.");
            }
        }

        private void laPlacianPointDetectionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Bitmap image = new Bitmap(this.picBoxDisplay.Image);
            NeighbourhoodOperations laPlacianEdgeDetection = new NeighbourhoodOperations(image, 3);
            this.picBoxDisplay.Image = laPlacianEdgeDetection.LaPlacianEdgeDetection();
            this.DrawHistogram(this.ckboxGrey.TabIndex);
        }

        private void laplacianToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.laplacian();
        }

        /// <summary>
        /// Calls on Laplacian Function and returns sharped image
        /// </summary>
        private void laplacian()
        {

            Bitmap oldImage = (Bitmap)this.picBoxDisplay.Image;
            Bitmap newImage;
            Sharpening sharpening = new Sharpening(oldImage);
            newImage = sharpening.Laplacian();
            this.picBoxDisplay.Image = (Image)newImage;
        }

        /// <summary>
        /// Calls on HorizontalSharpening Function and returns sharped image
        /// </summary>
        private void HorizontalLineSharpening()
        {
            Bitmap oldImage = (Bitmap)this.picBoxDisplay.Image;
            Bitmap newImage;
            Sharpening horizontalSharpening = new Sharpening(oldImage);
            newImage = horizontalSharpening.HorizontalSahrpening();
            this.picBoxDisplay.Image = (Image)newImage;
        }

        /// <summary>
        /// Calls on VerticalSharpening Function and returns sharped image
        /// </summary>
        private void VerticalLineSharpening()
        {
            Bitmap oldImage = (Bitmap)this.picBoxDisplay.Image;
            Bitmap newImage;
            Sharpening verticalSharpening = new Sharpening(oldImage);
            newImage = verticalSharpening.VericalSahrpening();
            this.picBoxDisplay.Image = (Image)newImage;
        }

        /// <summary>
        /// Calls on Diagonal1Sahrpening '\' Function and returns sharped image
        /// </summary>
        private void Diagonal1LineSharpening()
        {
            Bitmap oldImage = (Bitmap)this.picBoxDisplay.Image;
            Bitmap newImage;
            Sharpening diagonalSharpening = new Sharpening(oldImage);
            newImage = diagonalSharpening.Diagonal1Sahrpening();
            this.picBoxDisplay.Image = (Image)newImage;
        }

        /// <summary>
        /// Calls on Diagonal2Sahrpening '/' Function and returns sharped image
        /// </summary>
        private void Diagonal2LineSharpening()
        {
            Bitmap oldImage = (Bitmap)this.picBoxDisplay.Image;
            Bitmap newImage;
            Sharpening diagona2Sharpening = new Sharpening(oldImage);
            newImage = diagona2Sharpening.Diagonal2Sahrpening();
            this.picBoxDisplay.Image = (Image)newImage;
        }

        private void histogramMatchingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            HistogramMatchingDialog dialog = new HistogramMatchingDialog((Bitmap)this.picBoxDisplay.Image);
            dialog.ShowDialog();
            this.picBoxDisplay.Image = (Image)dialog.ResultedImage;
        }

        private void customConvolutionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                CustomMatrix matrix = new CustomMatrix();
                CustomConvolution custom = new CustomConvolution(ref matrix);
                custom.ShowDialog();
                Bitmap image = new Bitmap(this.picBoxDisplay.Image);
                NeighbourhoodOperations convolution = new NeighbourhoodOperations(image, matrix.MatrixSize);
                this.picBoxDisplay.Image = convolution.Convolution(matrix.Matrix, matrix.Type);
                this.DrawHistogram(this.ckboxGrey.TabIndex);
            }
            catch
            {
                MessageBox.Show("Error using Custom Convolution.", "Error");
            }
        }

        private void btnSmooth_Click(object sender, EventArgs e)
        {
            try
            {
                Bitmap img = new Bitmap(this.picBoxDisplay.Image);
                NeighbourhoodOperations smooth;
                if (this.radBtnMean.Checked)
                {
                    smooth = new NeighbourhoodOperations(img, int.Parse(this.txtBoxSmooth.Text));
                    this.picBoxDisplay.Image = smooth.MeanFilter();
                }
                else if (radBtnGaussian.Checked)
                {
                    int maskSize = ((int)((3.7 * (float.Parse(this.txtBoxSmooth.Text))) - 0.5) * 2) + 1;
                    smooth = new NeighbourhoodOperations(img, maskSize);
                    this.picBoxDisplay.Image = smooth.GaussianFilter(float.Parse(this.txtBoxSmooth.Text));
                }
            }
            catch
            {
                MessageBox.Show("Error occured during image smoothing.");
            }
        }

        private void radBtnMean_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void radBtnGaussian_CheckedChanged(object sender, EventArgs e)
        {
            if (this.radBtnGaussian.Checked)
            {
                this.label2.Visible = true;
                this.label1.Visible = false;
            }
            else
            {
                this.label2.Visible = false;
                this.label1.Visible = true;
            }
        }

        private void openToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            try
            {
                this.picBoxDisplay.Image = control.OpenImage();
                if (this.picBoxDisplay.Image != null)
                {
                    this.ckboxGrey.Checked = true;
                    this.ckboxRed.Checked = false;
                    this.ckboxGreen.Checked = false;
                    this.ckboxBlue.Checked = false;
                    this.DrawHistogram(this.ckboxGrey.TabIndex);
                }
            }
            catch
            {
                MessageBox.Show("Error opening image.");
            }
        }

        private void bilinearToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            try
            {
                Dimentions dimentions = new Dimentions();
                ResizeDialog dialog = new ResizeDialog(this.picBoxDisplay.Image.Width, this.picBoxDisplay.Image.Height, ref dimentions);
                dialog.ShowDialog();

                this.picBoxDisplay.Image = geometry.BilinearResize(this.picBoxDisplay.Image, dimentions.Width, dimentions.Height);
            }
            catch
            {
                MessageBox.Show("Error resizing image.");
            }
        }

        private void clockwiseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                this.picBoxDisplay.Image = geometry.Rotate(this.picBoxDisplay.Image, true);
            }
            catch
            {
                MessageBox.Show("Error rotating image.");
            }
        }

        private void antiClockwiseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                this.picBoxDisplay.Image = geometry.Rotate(this.picBoxDisplay.Image, false);
            }
            catch
            {
                MessageBox.Show("Error rotating image.");
            }
        }

        private void translateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                Dimentions dimentions = new Dimentions();
                TranslateDialog translate = new TranslateDialog(ref dimentions);
                translate.ShowDialog();
                this.picBoxDisplay.Image = geometry.Translate(this.picBoxDisplay.Image, dimentions.Width, dimentions.Height);
            }
            catch
            {
                MessageBox.Show("Error translating image.");
            }
        }

        private void ckboxRed_CheckedChanged(object sender, EventArgs e)
        {
            if (this.ckboxRed.Checked)
            {
                this.DrawHistogram(this.ckboxRed.TabIndex);
                this.chartHist.Series[0].IsVisibleInLegend = true;
            }
            else
            {
                this.chartHist.Series[0].Points.Clear();
                this.chartHist.Series[0].IsVisibleInLegend = false;
            }
        }

        private void ckboxGreen_CheckedChanged(object sender, EventArgs e)
        {
            if (this.ckboxGreen.Checked)
            {
                this.DrawHistogram(this.ckboxGreen.TabIndex);
                this.chartHist.Series[1].IsVisibleInLegend = true;
            }
            else
            {
                this.chartHist.Series[1].Points.Clear();
                this.chartHist.Series[1].IsVisibleInLegend = false;
            }
        }

        private void ckboxBlue_CheckedChanged(object sender, EventArgs e)
        {
            if (this.ckboxBlue.Checked)
            {
                this.DrawHistogram(this.ckboxBlue.TabIndex);
                this.chartHist.Series[2].IsVisibleInLegend = true;
            }
            else
            {
                this.chartHist.Series[2].Points.Clear();
                this.chartHist.Series[2].IsVisibleInLegend = false;
            }
        }

        private void ckboxGrey_CheckedChanged(object sender, EventArgs e)
        {
            if (this.ckboxGrey.Checked)
            {
                this.DrawHistogram(this.ckboxGrey.TabIndex);
                this.chartHist.Series[3].IsVisibleInLegend = true;
            }
            else
            {
                this.chartHist.Series[3].Points.Clear();
                this.chartHist.Series[3].IsVisibleInLegend = false;
            }
        }

        private void quantizationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                Dimentions dimentions = new Dimentions();
                QuantizationDialog dialog = new QuantizationDialog(ref dimentions);
                dialog.ShowDialog();
                ImageEnhancement quantization = new ImageEnhancement(this.picBoxDisplay.Image);
                this.picBoxDisplay.Image = quantization.Quantization(dimentions.Value);
                this.DrawHistogram(this.ckboxGrey.TabIndex);
            }
            catch
            {
                MessageBox.Show("Image quanization malfunction.");
            }
        }

        private void equalizationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                ImageEnhancement enhancement = new ImageEnhancement(this.picBoxDisplay.Image);
                this.picBoxDisplay.Image = enhancement.Equalization((Bitmap)this.picBoxDisplay.Image);
                this.DrawHistogram(this.ckboxGrey.TabIndex);
                this.ckboxRed.Checked = false;
                this.ckboxGreen.Checked = false;
                this.ckboxBlue.Checked = false;
            }
            catch
            {
                MessageBox.Show("Equalization malfunction.");
            }
        }

        private void contrastToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                Dimentions dimentions = new Dimentions();
                ContrastDialog dialog = new ContrastDialog(ref dimentions);
                dialog.ShowDialog();
                ImageEnhancement contrast = new ImageEnhancement(this.picBoxDisplay.Image);
                this.picBoxDisplay.Image = contrast.Contrast(dimentions.Minimum, dimentions.Maximum);
                this.DrawHistogram(this.ckboxGrey.TabIndex);
            }
            catch
            {
                MessageBox.Show("Image contrast operation error.");
            }
        }

        private void addToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                ArithmeticOperations arithmetic = new ArithmeticOperations((int)arithmeticOp.add);
                arithmetic.ShowDialog();
            }
            catch
            {
                MessageBox.Show("Error executing 'Add' Arithmatic operation.");
            }
        }

        private void subtractToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                ArithmeticOperations arithmetic = new ArithmeticOperations((int)arithmeticOp.sub);
                arithmetic.ShowDialog();
            }
            catch
            {
                MessageBox.Show("Error executing 'Subtract' Arithmatic operation.");
            }
        }

        private void horizontalToolStripMenuItem1_Click_1(object sender, EventArgs e)
        {
            try
            {
                Bitmap image = new Bitmap(this.picBoxDisplay.Image);
                NeighbourhoodOperations lineDetection = new NeighbourhoodOperations(image, 3);
                this.picBoxDisplay.Image = lineDetection.KirschLineDetection(NeighbourhoodOperations.LineDetectionType.Horizontal);
                this.DrawHistogram(this.ckboxGrey.TabIndex);
            }
            catch
            {
                MessageBox.Show("Error in Line Detection Operation.", "Error");
            }
        }

        private void verticalToolStripMenuItem2_Click_1(object sender, EventArgs e)
        {
            try
            {
                Bitmap image = new Bitmap(this.picBoxDisplay.Image);
                NeighbourhoodOperations lineDetection = new NeighbourhoodOperations(image, 3);
                this.picBoxDisplay.Image = lineDetection.KirschLineDetection(NeighbourhoodOperations.LineDetectionType.Vertical);
                this.DrawHistogram(this.ckboxGrey.TabIndex);
            }
            catch
            {
                MessageBox.Show("Error in Line Detection Operation.", "Error");
            }
        }

        private void diagonalToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            try
            {
                Bitmap image = new Bitmap(this.picBoxDisplay.Image);
                NeighbourhoodOperations lineDetection = new NeighbourhoodOperations(image, 3);
                this.picBoxDisplay.Image = lineDetection.KirschLineDetection(NeighbourhoodOperations.LineDetectionType.LeftDiagonal);
                this.DrawHistogram(this.ckboxGrey.TabIndex);
            }
            catch
            {
                MessageBox.Show("Error in Line Detection Operation.", "Error");
            }
        }

        private void diagonalToolStripMenuItem1_Click_1(object sender, EventArgs e)
        {
            try
            {
                Bitmap image = new Bitmap(this.picBoxDisplay.Image);
                NeighbourhoodOperations lineDetection = new NeighbourhoodOperations(image, 3);
                this.picBoxDisplay.Image = lineDetection.KirschLineDetection(NeighbourhoodOperations.LineDetectionType.RightDiagonal);
                this.DrawHistogram(this.ckboxGrey.TabIndex);
            }
            catch
            {
                MessageBox.Show("Error in Line Detection Operation.", "Error");
            }
        }

        private void horizontalToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            this.HorizontalLineSharpening();
        }

        private void verticalToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            this.VerticalLineSharpening();
        }

        private void diagonal1ToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            this.Diagonal1LineSharpening();
        }

        private void diagonal2ToolStripMenuItem1_Click_1(object sender, EventArgs e)
        {
            this.Diagonal2LineSharpening();
        }

        private void fourToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FourierTransform fourier = new FourierTransform(this.picBoxDisplay.Image);
            fourier.Show();
        }

        private void btnNoise_Click(object sender, EventArgs e)
        {
            AddingNoise addingNoise = new AddingNoise(this.picBoxDisplay.Image);
            addingNoise.Show();
        }
        
        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Bitmap bitmapSave = new Bitmap(this.picBoxDisplay.Image);
            bitmapSave.Save("MainImage" + count.ToString() + ".bmp");
            count++;
        }

        private void btnPeriodicNoise_Click(object sender, EventArgs e)
        {
            PeriodicNoise noise = new PeriodicNoise(this.picBoxDisplay.Image);
            noise.ShowDialog();
        }

        private void localEnhancementStatisticsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Dimentions dim = new Dimentions();   
            LocalEnhancementStatisticsDialog dialog = new LocalEnhancementStatisticsDialog(ref dim);
            dialog.ShowDialog();
            ImageEnhancement enhance = new ImageEnhancement(this.picBoxDisplay.Image);
            this.picBoxDisplay.Image = enhance.LocalEnhancement(dim.ListDouble, dim.Value);
        }

        private void btnMorphology_Click(object sender, EventArgs e)
        {
            Morphology morphology = new Morphology(this.picBoxDisplay.Image);
            morphology.Show();
        }

        private void binaryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Dimentions dim = new Dimentions();
            Thresholding threshold=new Thresholding(ref dim);
            threshold.ShowDialog();
            Colour binary = new Colour();
            Bitmap image = new Bitmap(this.picBoxDisplay.Image);
            this.picBoxDisplay.Image = binary.BinaryImage(image, dim.Value);
        }

        private void localHistogramEqualizationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Dimentions dim = new Dimentions();
            EqualizationDialog dialog = new EqualizationDialog(ref dim);
            dialog.ShowDialog();
            ImageEnhancement enhance = new ImageEnhancement(this.picBoxDisplay.Image);
            this.picBoxDisplay.Image = enhance.LocalEqualization(dim.Value);
        }
    }
}
